/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.p2psimulator.analysis;

import org.p2psimulator.entity.Message;
import org.p2psimulator.entity.Network;
import org.p2psimulator.entity.Peer;
import org.p2psimulator.entity.behavior.BehaviorTypes;
import org.p2psimulator.entity.protocol.messages.MessageTypes;
import org.p2psimulator.entity.protocol.messages.general.DownloadAnswerMessage;
import org.p2psimulator.entity.protocol.messages.general.DownloadRequestMessage;
import org.p2psimulator.util.SystemLogger;

/**
 *
 * @author Amorim
 */
public class NetworkInfoCollector extends InfoCollector<Network, Message> {

    int messageCount;
    SimulationChart<Integer, Double> sendMessagesByType;
    SimulationChart<Integer, Double> requestsMessagesByType;
    SimulationChart<Integer, Double> offerMessagesByType;
    SimulationChart<Integer, Double> totalMessages;
    SimulationChart<Integer, Double> totalNonQueryMessages;
    SimulationChart<Integer, Double> discardedMessages;
    SimulationChart<Integer, Double> discardedMessagesRate;
    Message currentMessage;

    public NetworkInfoCollector() {
        super();

        sendMessagesByType = new SimulationChart<Integer, Double>(
                "SENT MESSAGES by PEER TYPE");

        sendMessagesByType.setXlabel("Tick");
        sendMessagesByType.setYlabel("Number of Messages");

        requestsMessagesByType = new SimulationChart<Integer, Double>(
                "DOWNLOAD REQUESTS by PEER TYPE");

        requestsMessagesByType.setXlabel("Tick");
        requestsMessagesByType.setYlabel("Number of Messages");

        offerMessagesByType = new SimulationChart<Integer, Double>(
                "DOWNLOAD OFFERS by PEER TYPE");

        offerMessagesByType.setXlabel("Tick");
        offerMessagesByType.setYlabel("Number of Messages");

        totalMessages = new SimulationChart<Integer, Double>(
                "NETWORK TRAFFIC");

        totalMessages.setXlabel("Tick");
        totalMessages.setYlabel("Number of Messages");

        totalNonQueryMessages = new SimulationChart<Integer, Double>(
                "REPUTATION SYSTEM'S MESSAGES");

        totalNonQueryMessages.setXlabel("Tick");
        totalNonQueryMessages.setYlabel("Number of Messages");

        discardedMessages = new SimulationChart<Integer, Double>(
                "DISCARDED MESSAGES");
        discardedMessages.setXlabel("Tick");
        discardedMessages.setYlabel("Number of Messages");

        discardedMessagesRate = new SimulationChart<Integer, Double>(
                "DISCARDED MESSAGES RATE");
        discardedMessagesRate.setXlabel("Tick");
        discardedMessagesRate.setYlabel("Message rate (%)");
    }

    public synchronized void incMessageCount(){
        messageCount++;
    }
    @Override
    public void collectInfo(Network network, Message msg) {
        collectNetworkInfo(network, msg);
    }

    public synchronized void collectNetworkInfo(Network network, Message msg) {

        // gráfico 1
        BehaviorTypes behaviorType = msg.getOriginBehavior();
        double value = sendMessagesByType.getDataset().getValue(
                behaviorType.getTypeName(), network.getCurrentTick()) != null ? sendMessagesByType.getDataset().getValue(behaviorType.getTypeName(), network.getCurrentTick())
                : 0;
        value++;
        sendMessagesByType.getDataset().putValue(behaviorType.getTypeName(),
                network.getCurrentTick(), value);

        // grafico 2
        if (msg instanceof DownloadRequestMessage) {

            Peer p = network.getEnvironment().getPeerBank().getPeerMap().get(msg.getDestination());
            behaviorType = p.getBehavior().getBehaviorType();
            value = requestsMessagesByType.getDataset().getValue(
                    behaviorType.getTypeName(), network.getCurrentTick()) != null ? requestsMessagesByType.getDataset().getValue(behaviorType.getTypeName(),
                    network.getCurrentTick())
                    : 0;
            value++;
            requestsMessagesByType.getDataset().putValue(
                    behaviorType.getTypeName(), network.getCurrentTick(), value);
        } else if (msg instanceof DownloadAnswerMessage) {
            Peer p = network.getEnvironment().getPeerBank().getPeerMap().get(msg.getServentId());
            behaviorType = p.getBehavior().getBehaviorType();

            value = offerMessagesByType.getDataset().getValue(
                    behaviorType.getTypeName(), network.getCurrentTick()) != null ? offerMessagesByType.getDataset().getValue(behaviorType.getTypeName(),
                    network.getCurrentTick())
                    : 0;
            value++;

            offerMessagesByType.getDataset().putValue(behaviorType.getTypeName(), network.getCurrentTick(), value);
        }

        // grÁfico 3
        MessageTypes messageType = msg.getMessageType();
        value = totalMessages.getDataset().getValue(messageType.getName(),
                network.getCurrentTick()) != null ? totalMessages.getDataset().getValue(
                messageType.getName(), network.getCurrentTick()) : 0;
        value++;
        totalMessages.getDataset().putValue(messageType.getName(), network.getCurrentTick(),
                value);

        if (messageType != MessageTypes.QUERY_MESSAGE
                && messageType != MessageTypes.QUERY_HIT_MESSAGE
                && messageType != MessageTypes.PING_MESSAGE
                && messageType != MessageTypes.PONG_MESSAGE
                && messageType != MessageTypes.DOWNLOAD_ANSWARE_MESSAGE
                && messageType != MessageTypes.DOWNLOAD_REQUEST_MESSAGE) {
            value = totalNonQueryMessages.getDataset().getValue(
                    messageType.getName(), network.getCurrentTick()) != null ? totalNonQueryMessages.getDataset().getValue(messageType.getName(), network.getCurrentTick())
                    : 0;
            value++;
            totalNonQueryMessages.getDataset().putValue(messageType.getName(),
                    network.getCurrentTick(), value);
        }
    }

    /**
     * Coleta uma mensagem descartada por um peer
     *
     * @param msg
     */
    public synchronized void collectDiscardedMessage(Network network, Message msg) {

        // gráfico 4
        MessageTypes messageType = msg.getMessageType();
        double value = discardedMessages.getDataset().getValue(
                messageType.getName(), network.getCurrentTick()) != null ? 
                    discardedMessages.getDataset().getValue(messageType.getName(), network.getCurrentTick()) : 0;
        value++;
        discardedMessages.getDataset().putValue(messageType.getName(),
                network.getCurrentTick(), value);

        double total = totalMessages.getDataset().getValue(
                messageType.getName(), network.getCurrentTick()) != null ? 
                    totalMessages.getDataset().getValue(messageType.getName(), network.getCurrentTick()) : 1;

        double rate = (value / total) * 100;

        discardedMessagesRate.getDataset().putValue(messageType.getName(),
                network.getCurrentTick(), rate);

        SystemLogger.networkLogger.error(">>>> Mensagem descartada: [" + messageType.getName()
                + "] de: [" + msg.getOrigin() + "] para:[" + msg.getDestination() + "]");


    }

    public void cleanUp() {

        messageCount = 0;

        sendMessagesByType.clearDataset();

        requestsMessagesByType.clearDataset();

        offerMessagesByType.clearDataset();

        totalMessages.clearDataset();

        totalNonQueryMessages.clearDataset();

        discardedMessages.clearDataset();

        discardedMessagesRate.clearDataset();
    }

    public SimulationChart<Integer, Double> getDiscardedMessages() {
        return discardedMessages;
    }

    public void setDiscardedMessages(SimulationChart<Integer, Double> discardedMessages) {
        this.discardedMessages = discardedMessages;
    }

    public SimulationChart<Integer, Double> getDiscardedMessagesRate() {
        return discardedMessagesRate;
    }

    public void setDiscardedMessagesRate(SimulationChart<Integer, Double> discardedMessagesRate) {
        this.discardedMessagesRate = discardedMessagesRate;
    }

    public int getMessageCount() {
        return messageCount;
    }

    public void setMessageCount(int messageCount) {
        this.messageCount = messageCount;
    }

    public SimulationChart<Integer, Double> getOfferMessagesByType() {
        return offerMessagesByType;
    }

    public void setOfferMessagesByType(SimulationChart<Integer, Double> offerMessagesByType) {
        this.offerMessagesByType = offerMessagesByType;
    }

    public SimulationChart<Integer, Double> getRequestsMessagesByType() {
        return requestsMessagesByType;
    }

    public void setRequestsMessagesByType(SimulationChart<Integer, Double> requestsMessagesByType) {
        this.requestsMessagesByType = requestsMessagesByType;
    }

    public SimulationChart<Integer, Double> getSendMessagesByType() {
        return sendMessagesByType;
    }

    public void setSendMessagesByType(SimulationChart<Integer, Double> sendMessagesByType) {
        this.sendMessagesByType = sendMessagesByType;
    }

    public SimulationChart<Integer, Double> getTotalMessages() {
        return totalMessages;
    }

    public void setTotalMessages(SimulationChart<Integer, Double> totalMessages) {
        this.totalMessages = totalMessages;
    }

    public SimulationChart<Integer, Double> getTotalNonQueryMessages() {
        return totalNonQueryMessages;
    }

    public void setTotalNonQueryMessages(SimulationChart<Integer, Double> totalNonQueryMessages) {
        this.totalNonQueryMessages = totalNonQueryMessages;
    }
}
